<template>
  <div
    :style="{'height': height ? height : 'auto'}"
    class="list">
    <el-table
      :data="listData"
      :ref="tableRef"
      border
      size="small"
      height="100%"
      @current-change="currentChange"
      @sort-change="sortChange"
      @cell-dblclick="cellDoubleClick"
      @selection-change="selectionChange"
      @row-contextmenu="rowContextmenu">
      <el-table-column
        v-if="hasSelect"
        type="selection"
        width="55"
        align="center"
        >
      </el-table-column>
      <el-table-column
        v-for="col in cols"
        :key="col.prop"
        :prop="col.prop"
        :min-width="col.width"
        :label="col.label"
        :align="col.align || 'center'"
        :resizable="false" 
        show-overflow-tooltip 
        :sortable="col.sortable || false"
        >
        <template slot-scope="{row, column, $index}">
          <template v-if="col.slot">
            <slot :name="col.prop+'Slot'" :row="row" :column="column" :$index="$index"></slot>
          </template>
          <template v-else>
            {{ row[col.prop] }}
          </template>
        </template>
        
        <template slot="header" slot-scope="{column, $index}">
          <template v-if="col.headerSlot">
            <slot :name="col.prop+'HeaderSlot'" :column="column" :$index="$index"></slot>
          </template>
          <template v-else>
            {{ column.label }}
            <template v-if="col.headerContextMenus">
              <span style="float: right;" :class="[`${col.prop}-hmbtn`]" @click.stop="(e) => showHeaderMenu(col.prop, e)"><i class="el-icon-caret-bottom"></i></span>
              <!-- <list-header-menu
                :ref="col.prop+'-hm'"
                :element-id="col.prop+'-hm'"
                :options="_genHeaderMenus(col.headerContextMenus, col.prop)"
                @option-clicked="(v) => headerMenuClicked(v, col.prop)"
                /> -->
              <!-- <list-header-menu
                :ref="col.prop+'-hm'"
                :element-id="col.prop+'-hm'"
                :options="col.headerContextMenus"
                /> -->
            </template>
          </template>
        </template>    
      </el-table-column>
      <!-- 操作列 -->
      <el-table-column v-if="actionOpts.show" :label="actionOpts.name" :align="actionOpts.align" width="90">
        <template slot-scope="{row, column, $index}">
          <bs-edit-icon v-if="actionOpts.type.indexOf(1) > -1" @click.native="handleActionBtn('edit', row)"></bs-edit-icon>
          <bs-delete-icon v-if="actionOpts.type.indexOf(2) > -1" @click.native="handleActionBtn('del', row)"></bs-delete-icon>
          <el-button v-if="actionOpts.type.indexOf(3) > -1" class="detail-button" type="primary" size="mini" @click.native="handleActionBtn('detail', row)">查看</el-button>
        </template>
      </el-table-column>
    </el-table>

    <context-menu
      element-id="listContextMenu"
      ref="listContextMenu"
      @option-clicked="listContextMenuClicked"
      :options="contextMenus"
      ></context-menu>

    <!-- 头部菜单渲染 -->
    <list-header-menu
      v-for="col in hasHMCols"
      :key="col.prop+'-hm'"
      :ref="col.prop+'-hm'"
      :element-id="col.prop+'-hm'"
      :options="hmOptionsMap[col.prop]"
      @option-clicked="(v) => headerMenuClicked(v, col.prop)"
      />
  </div>
</template>

<script>
import ContextMenu from './components/SortContextMenu'
import ListHeaderMenu from './components/SortListHeaderMenu'

export default {
  name:'tablelist',
  components: {
    ContextMenu,
    ListHeaderMenu
  },
  props: {
    tableRef: {
      type: String,
      default() {
        return 'list'
      }
    },
    contextMenus: {
      type: Array,
      default() {
        return []
      }
    },
    sortable: {
      type: [Boolean, String],
      default: false
    },
    hasSelect: {
      type: Boolean,
      default: false
    },
    listData: {
      type: Array,
      default() {
        return []
      }
    },
    listCols: {
      type: Array,
      default() {
        return []
      }
    },
    initColsProps: { // 默认要显示的列的prop合集
      type: [Array, Boolean],
      default() {
        return false
      }
    },
    actionOpts: {
      type: Object,
      default() {
        return {
          show: true,
          align: 'center',
          width: '120px',
          type:[1,2],
          name:'操作'
        }
      }
    },
    height: {
      type: String,
      default: ''
    },
    initHeadmuneFlag: { // 初始化头部菜单标识
      type: [Boolean, String],
      default: 'auto'
    }
  },
  data() {
    return {
      activeItem: [],
      colFilterBoolMap: {}, // 列过滤是否启用索引
      colFilterValMap: {}, // 列过滤input值索引
      inputTimer: null, // input节流计时器
      hmOptionsMap: {}, // 头部菜单索引
      needShowColsMenu: [], // 显隐列菜单
      hmOpenedId: '', // 当前打开的头部菜单id
    } 
  },
  computed: {
    cols() {
      if (!this.initColsProps) {
        return [...this.listCols]
      } else if (this.initColsProps instanceof Array) {
        return this.listCols.filter(col => this.initColsProps.indexOf(col.prop) > -1)
      } else {
        return []
      }
    },
    hasHMCols() { // 拥有头部菜单的列
      return this.listCols.filter(col => col.headerContextMenus)
    }
  },
  watch: {
    'hasHMCols': {
      immediate: true,
      handler(v) {
        // console.log(this.initHeadmuneFlag)
        // if (this.initHeadmuneFlag !== 'auto') return ;
        const map = {}
        v.forEach(element => {
          map[element.prop] = this._genHeaderMenus(element.headerContextMenus, element.prop)
        });
        this.hmOptionsMap = map
      }
    },
    initHeadmuneFlag(v) {
      if (v === true) {
        const map = {}
        this.hasHMCols.forEach(element => {
          map[element.prop] = this._genHeaderMenus(element.headerContextMenus, element.prop)
        });
        this.hmOptionsMap = map
      }
    }
  },
  methods: {
    handleActionBtn(type, rowData) {
      this.$emit(`${type}Click`, JSON.parse(JSON.stringify(rowData)))
    },
    sortChange({ column, prop, order }) {
      this.sortable === 'custom' && this.$emit('sort-change', { column, prop, order })
    },
    selectionChange(selection) {
      this.activeItem = selection
      this.$emit('selection-change', selection)
    },
    cellDoubleClick(row, column, cell, event) {
      this.$emit('cell-double-click', row, column, cell, event)
    },
    currentChange(val){
      this.$emit('cunrrent-change', val)
    },
    getActiveItem() {
      return [...this.activeItem]
    },
    rowContextmenu(row, column, event) {
      if (this.contextMenus.length < 1) return ;
      event.preventDefault()
      this.$refs.listContextMenu.showMenu(event, row)
    },
    listContextMenuClicked(item) {
      if (this.contextMenus.length < 1) return ;
      this.$emit('contextMenuClicked', item)
    },
    showHeaderMenu(prop, event) {
      // console.log(this.$refs)
      // console.log(this.$refs[prop+'-hm'][0])
      const id = prop + '-hm'
      if (this.hmOpenedId && this.hmOpenedId !== id) {
        this.$refs[this.hmOpenedId][0].hideContextMenu()
      }
      this.$refs[prop+'-hm'][0].showMenu(event)
      this.hmOpenedId = id
    },
    headerMenuClicked(item, prop) {
      switch (item.option.type) {
        case 'sortUp':
          this.$emit('sort', {
            type: 'ASC',
            prop
          })
          break;
        case 'sortDown':
          this.$emit('sort', {
            type: 'DESC',
            prop
          })
          break;
        default:
      }
    },

    /*****    生成表头的额外功能菜单 开始      *****/
    _genHeaderMenus({width, items}, colProp) {
      const options = {} // 最终生成的额外功能配置
      const itemMap = {
        sortUp: {
          name: '升序',
          icon: 'iconfont icon-shengxu',
          type: 'sortUp'
        },
        sortDown: {
          name: '降序',
          icon: 'iconfont icon-jiangxu1',
          type: 'sortDown'
        },
        line: {
          type: 'divider'
        },
        cols: {
          name: '列',
          icon: 'iconfont icon-liebiao',
        },
        filter: {
          name: '过滤',
          type: 'checkbox'
        }
      }

      // 一层菜单的宽度设置
      options.width = width || '120px'
      // 一层菜单项生成
      options.items = items.map(item => {
        if (item === 'cols') { // 显隐列生成
          return {
            ...itemMap.cols,
            children: this._genColsMenu()
          }
        } else if (item === 'filter') { // 过滤功能
          const filter = {
            ...itemMap.filter,
            value: false,
            changeFn: (v) => {
              this._filterCheckChange(v, colProp)
            },
            children: this._genFilterMenu(colProp)
          }
          this.$set(this.colFilterBoolMap, colProp, filter)
          // this.colFilterBoolMap[colProp] = filter
          return filter

        } else {
          return itemMap[item]
        }
      })

      return options
    },
    // 生成列显隐菜单
    _genColsMenu() {
      const menu = {}
      menu.width = '180px'
      
      if (this.needShowColsMenu.length < 1) {
        this.needShowColsMenu = this.listCols.map(col => {
          return {
            type: 'checkbox',
            name: col.label,
            value: this.initColsProps.indexOf(col.prop) > -1,
            changeFn: (v) => {
              this._colsChange(v, col.prop)
            }
          }
        })
      }
      menu.items = this.needShowColsMenu

      return menu
    },
    // 列显隐菜单事件回调
    _colsChange(isShow, prop) {
      const _initColsProps = [...this.initColsProps]
      if (isShow) {
        _initColsProps.push(prop)
      } else {
        _initColsProps.splice(_initColsProps.indexOf(prop), 1)
      }
      this.$emit('update:initColsProps', _initColsProps)
    },
    // 生成过滤菜单
    _genFilterMenu(colProp) {
      // const _pureColFilterValMap = JSON.parse(JSON.stringify(this.colFilterValMap))
      // console.log(_pureColFilterValMap, '---2')
      const menu = {}
      menu.width = '160px'
      const filterInput = {
        class: 'filter-input',
        type: 'input',
        icon: 'iconfont icon-shaixuan',
        value: '',
        changeFn: (v) => {
          this._inputChange(v, colProp)
        },
      }
      this.$set(this.colFilterValMap, colProp, filterInput)
      // this.colFilterValMap[colProp] = filterInput
      menu.items = [
        filterInput
      ]
      return menu
    },
    // 过滤input框事件回调
    _inputChange(v, colProp) {
      if (this.inputTimer) {
        clearTimeout(this.inputTimer)
      }
      this.inputTimer = setTimeout(() => {
        this.$emit('filter', {
          value: v,
          prop: colProp
        })
        this.$nextTick(() => {
          if (!v) {
            this.colFilterBoolMap[colProp].value = false
          } else if (!this.colFilterBoolMap[colProp].value){
            this.colFilterBoolMap[colProp].value = true
          }
        })
      }, 800)
    },
    // 过滤checkbox事件回调
    _filterCheckChange(v, colProp) {
      // 开启 - 传input值  关闭 - 传空字符串
      this.$emit('filter', {
        value: v ? this.colFilterValMap[colProp].value : '',
        prop: colProp
      })
    },
    clearSelection(){
      this.$refs.list.clearSelection()
    }
    /*****    生成表头的额外功能菜单 结束      *****/
  },
  mounted() {
    // console.log(this.listCols)
  },
  beforeDestroy() {
    this.inputTimer && clearTimeout(this.inputTimer)
  }
}
</script>

<style scoped>
.list {
  position: relative;
}
::v-deep .vue-simple-context-menu2__item{color:#ccc !important;}
::v-deep .iconfont{font-size:14px!important;}
::v-deep .icon-shaixuan{font-size:20px!important;}


</style>
<style lang="scss" scoped>
.edit {
  color: $bg-33;
}
</style>